package org.fg.logserver.config;

import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.net.server.ServerSocketReceiver;
import ch.qos.logback.classic.sift.MDCBasedDiscriminator;
import ch.qos.logback.classic.sift.SiftingAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.util.Duration;
import lombok.extern.slf4j.Slf4j;
import org.fg.logcommon.Constant;
import org.fg.logcommon.config.DefaultDiscriminatorFilter;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Configuration;

import java.nio.charset.Charset;

@Slf4j
@Configuration
public class AppRunner implements CommandLineRunner {

    @Override
    public void run(String... args) {
        addReceiverAndAppend();
    }

    private static void addReceiverAndAppend() {
        Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
        LoggerContext lc = root.getLoggerContext();
        ServerSocketReceiver receiver = new ServerSocketReceiver();
        receiver.setPort(9977);
        receiver.setContext(lc);
        receiver.setBacklog(1000);
        lc.register(receiver);
        receiver.start();

        Appender<ILoggingEvent> append = addAppend(lc);
        root.addAppender(append);
    }


    private static Appender<ILoggingEvent> addAppend(LoggerContext lc) {
        SiftingAppender siftingAppender = new SiftingAppender();
        MDCBasedDiscriminator discriminator = new MDCBasedDiscriminator();
        discriminator.setContext(lc);
        discriminator.setKey(Constant.MDC_KEY);
        discriminator.setDefaultValue("default");
        discriminator.start();
        siftingAppender.setDiscriminator(discriminator);
        siftingAppender.setName("SIFT");
        siftingAppender.setContext(lc);
        siftingAppender.setAppenderFactory((context, discriminatingValue) -> {
            FileAppender<ILoggingEvent> fileAppender = new FileAppender<>();
            PatternLayoutEncoder encoder = new PatternLayoutEncoder();
            encoder.setContext(context);
            encoder.setPattern("%X{mdc_key} - %d{yyyy-MM-dd HH:mm:ss.SSS} - [%25.25(%thread)] - [%-5level] - %-30.30(%logger{30}) : %msg%n");
            encoder.setCharset(Charset.defaultCharset());
            fileAppender.setEncoder(encoder);
            fileAppender.setName(discriminatingValue);
            fileAppender.setContext(context);
            fileAppender.setFile("D:\\tmp\\log-" + discriminatingValue + ".log");
            encoder.start();
            fileAppender.start();
            return fileAppender;
        });
        siftingAppender.setMaxAppenderCount(10000);
        siftingAppender.start();

        siftingAppender.setTimeout(Duration.buildByMinutes(10));

        DefaultDiscriminatorFilter defaultDiscriminatorFilter = new DefaultDiscriminatorFilter();
        defaultDiscriminatorFilter.setKey(Constant.MDC_KEY);
        defaultDiscriminatorFilter.setDefaultValue("default");
        defaultDiscriminatorFilter.start();
        siftingAppender.addFilter(defaultDiscriminatorFilter);

        return siftingAppender;
    }
}
